package cog.support.util.serializable.util;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.BaseLocaleConverter;

import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

/**
 * LocalDate的转化器,用于BeanUtils中，正对浴Java 8的相关时间方面的转化
 *
 * @author 陈杰
 * @since 2017年1月9日17:53:14
 * @version v0.1
 *
 * Copyright ChenJie(chenjie_java@aliyun.com) 2016年9月12日 00:53:51
 */
public class LocalDateConverter extends BaseLocaleConverter {
    public enum ConverterDateType {
        LOCAL_DATE_TIME,LOCAL_TIME,LOCAL_DATE,Instant
    }

    private ConverterDateType converterDateType;
    /**
     * LocalDateTime的格式化
     * */
    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * LocalDate的格式化
     * */
    private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * LocaTime的格式化
     * */
    private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");

    public LocalDateConverter() {super(Locale.getDefault(),"");this.converterDateType = ConverterDateType.LOCAL_DATE_TIME;}

    public LocalDateConverter(ConverterDateType converterDateType) {
        super(Locale.getDefault(),"");
        this.converterDateType = converterDateType;
    }

    private static LocalDateConverter newInstance(ConverterDateType converterDateType){
        return new LocalDateConverter(converterDateType);
    }

    protected LocalDateConverter(Locale locale, String pattern) {
        super(locale, pattern);
    }

    protected LocalDateConverter(Locale locale, String pattern, boolean locPattern) {
        super(locale, pattern, locPattern);
    }

    protected LocalDateConverter(Object defaultValue, Locale locale, String pattern) {
        super(defaultValue, locale, pattern);
    }

    protected LocalDateConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
        super(defaultValue, locale, pattern, locPattern);
    }

    public void registerConvertUtils(){
        ConvertUtils.register(this,LocalDateTime.class);
        ConvertUtils.register(LocalDateConverter.newInstance(ConverterDateType.LOCAL_DATE),LocalDate.class);
        ConvertUtils.register(LocalDateConverter.newInstance(ConverterDateType.LOCAL_TIME),LocalTime.class);
        ConvertUtils.register(LocalDateConverter.newInstance(ConverterDateType.Instant),Instant.class);
    }

    @Override
    public <T> T convert(final Class<T> type, final Object value, final String pattern) {
        if (type.isInstance(value)) {
            return type.cast(value);
        }else{
            return super.convert(type,value,pattern);
        }
    }

    @Override
    protected Object parse(Object o, String s) throws ParseException {
        Object returnObject = null; boolean toString = this.checkConvertType(o);
        switch (this.converterDateType){
            case LOCAL_DATE_TIME:
                returnObject = toString ? ((LocalDateTime)o).format(dateTimeFormatter) : LocalDateTime.parse(o.toString(),dateTimeFormatter);
                break;
            case LOCAL_DATE:
                returnObject = toString ? ((LocalDate)o).format(dateFormatter) : LocalDate.parse(o.toString(),dateFormatter);
                break;
            case LOCAL_TIME:
                returnObject = toString ? ((LocalTime)o).format(timeFormatter) : LocalTime.parse(o.toString(),timeFormatter);
                break;
            case Instant:
                returnObject = toString ? DateTimeFormatter.ISO_INSTANT.format((Instant)o) : Instant.parse(o.toString());
                break;
        }

        return returnObject;
    }

    protected boolean checkConvertType(Object o) throws ParseException {
        if(o instanceof LocalTime || o instanceof LocalDate || o instanceof LocalDateTime) return true;
        else if(o instanceof String) return false;
        else throw new ParseException("不支持"+o.getClass().getName()+"到LocalDate系列的类型转换",2);
    }
}

